﻿using Jst.Core.Configuration;
using Jst.Core.Utility;
using Microsoft.IdentityModel.Tokens;
using SqlSugar.Extensions;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;


namespace Jst.Core.jwt
{
    /// <summary>
    /// JWTToken生成类
    /// </summary>
    public class JwtToken
    {
        /// <summary>
        /// 获取基于JWT的Token
        /// </summary>
        /// <param name="claims">需要在登陆的时候配置</param>
        /// <param name="permissionRequirement">在startup中定义的参数</param>
        /// <param name="newSigningKey">新签名</param>
        /// <returns></returns>
        public static dynamic BuildJwtToken(Claim[] claims, PermissionRequirement permissionRequirement, string newSigningKey)
        {
            var now = DateTime.Now;
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(newSigningKey));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
            // 实例化JwtSecurityToken
            var jwt = new JwtSecurityToken(
                issuer: AppSettingsConstVars.JwtConfigIssuer,
                audience: AppSettingsConstVars.JwtConfigAudience,
                claims: claims,
                expires: DateTime.UtcNow.AddMinutes(30), // 设置过期时间
                signingCredentials: credentials
             );

            // 生成 Token
            var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
            var responseJson = new JwtTokenResponseJson();

            if (ValidateJwtToken(encodedJwt, newSigningKey))
            {
                //打包返回前台
                responseJson = new JwtTokenResponseJson
                {
                    Success = true,
                    Token = encodedJwt,
                    Expires_in = permissionRequirement.Expiration.TotalSeconds,
                    token_type = "Bearer"
                };
            }

            return responseJson;
        }

        /// <summary>
        /// 签名验证
        /// </summary>
        /// <param name="jwtToken"></param>
        /// <param name="signingKey"></param>
        /// <returns></returns>
        public static bool ValidateJwtToken(string jwtToken, string signingKey)
        {
            var validationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = AppSettingsConstVars.JwtConfigIssuer,
                ValidAudience = AppSettingsConstVars.JwtConfigAudience,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signingKey))
            };

            try
            {
                var handler = new JwtSecurityTokenHandler();
                handler.ValidateToken(jwtToken, validationParameters, out var validatedToken);
                return true;
            }
            catch (SecurityTokenException ex)
            {
                throw new Exception("JWT token validation failed.", ex);
            }
        }


        /// <summary>
        /// 解析
        /// </summary>
        /// <param name="jwtStr"></param>
        /// <returns></returns>
        public static TokenModelJwt SerializeJwt(string jwtStr)
        {
            var jwtHandler = new JwtSecurityTokenHandler();
            TokenModelJwt tokenModelJwt = new TokenModelJwt();

            // token校验
            if (!string.IsNullOrEmpty(jwtStr) && jwtHandler.CanReadToken(jwtStr))
            {

                JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);

                object role;

                jwtToken.Payload.TryGetValue(ClaimTypes.Role, out role);

                tokenModelJwt = new TokenModelJwt
                {
                    Uid = (jwtToken.Id).ObjectToLong(),
                    Role = role != null ? role.ObjectToString() : "",
                };
            }
            return tokenModelJwt;
        }


        public static bool customSafeVerify(string token)
        {
            var jwtHandler = new JwtSecurityTokenHandler();
            var symmetricKeyAsBase64 = AppSettingsConstVars.JwtConfigSecretKey;
            var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
            var signingKey = new SymmetricSecurityKey(keyByteArray);
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

            var jwt = jwtHandler.ReadJwtToken(token);
            return jwt.RawSignature == Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(jwt.RawHeader + "." + jwt.RawPayload, signingCredentials);
        }

    }

    /// <summary>
    /// JwtToken生成返回
    /// </summary>
    public class JwtTokenResponseJson
    {
        public bool Success { get; set; } = false;
        public string Token { get; set; }
        public double Expires_in { get; set; }
        public string token_type { get; set; }

    }


    /// <summary>
    /// 令牌
    /// </summary>
    public class TokenModelJwt
    {
        /// <summary>
        /// Id
        /// </summary>
        public long Uid { get; set; }
        /// <summary>
        /// 角色
        /// </summary>
        public string Role { get; set; }
        /// <summary>
        /// 职能
        /// </summary>
        public string Work { get; set; }

    }
}
